package com.youlu.campus.service.visitor;

import com.alibaba.fastjson.JSON;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.base.university.UniversityBase;
import com.youlu.campus.common.enums.PlatformEnum;
import com.youlu.campus.common.utils.TimeUtils;
import com.youlu.campus.entity.H5UserPO;
import com.youlu.campus.entity.MemberShipInfo;
import com.youlu.campus.entity.QQH5UserPO;
import com.youlu.campus.entity.QQMiniUserPO;
import com.youlu.campus.entity.UniversityInfo;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.entity.UserParticipateActivityInfo;
import com.youlu.campus.entity.VO.req.CheckMobileVO;
import com.youlu.campus.entity.VO.res.VisitorUserInfoRes;
import com.youlu.campus.entity.WechatH5UserPO;
import com.youlu.campus.entity.WechatMiniUserPO;
import com.youlu.campus.entity.douyin.DouYinMiniUserPO;
import com.youlu.campus.service.job.JobInfoService;
import com.youlu.campus.service.university.UniversityInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class VisitorUserServiceImpl implements VisitorUserService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private JobInfoService jobInfoService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private UniversityInfoService universityInfoService;
    @Value("${sys.defaultHeadUrl}")
    private String defaultHeadUrl;

    private String userMoveFormatKey = "com.luyou.user.movement_step.%s";

    private String userDaKaRedisKey = "com.luyou.user.daka.%s.%s";

    private String defaultUserRedisKey = "com.luyou.user.default.mobile.%s";
    /**
     * 用户Key
     */
    private String ALL_RANK_USER_KEY = "com.luyou.rank.user.userId:%s.platform:%s";

    @Override
    public UserPO getUser(String platform, String appId, String openId) {
        log.info(":>>> 开始获取用户信息platform:{},appId:{},openId{}", platform, appId, openId);
        if (StringUtils.isBlank(platform) || StringUtils.isBlank(openId)) {
            log.error(":>>> 获取用户信息参数错误:平台或openId为空");
            throw new BusinessException("获取用户信息参数错误");
        }
        switch (platform) {
            case "qq-h5": {
                Query query = new Query().addCriteria(Criteria.where("openId").is(openId));
//                if (StringUtils.isNotBlank(appId)) {
//                    query.addCriteria(Criteria.where("appId").is(appId));
//                }
                String userId = null;
                QQH5UserPO qQH5UserPO = mongoTemplate.findOne(query, QQH5UserPO.class);
                if (Objects.isNull(qQH5UserPO)) {
                    log.error(":>>> QQ-H5 用户不存在:{}", openId);
                    return null;
                }
                userId = qQH5UserPO.getAccountInfoId();
                UserPO userPO = new UserPO();
                BeanUtils.copyProperties(qQH5UserPO, userPO);
                userPO.setId(userId);
                return userPO;
            }
            case "qq":
                log.info(":>>> 平台:qq");
                return this.getUserByOpenId(openId);
            case "wechat-h5": {
                log.info(":>>> 平台:wechat-h5");
                Query query = new Query().addCriteria(Criteria.where("openId").is(openId));
//                if (StringUtils.isNotBlank(appId)) {
//                    query.addCriteria(Criteria.where("appId").is(appId));
//                }
                String userId = null;
                WechatH5UserPO wechatH5UserPO = mongoTemplate.findOne(query, WechatH5UserPO.class);
                if (Objects.isNull(wechatH5UserPO)) {
                    log.error(":>>> 微信用户不存在:{}", openId);
                    return null;
                }
                userId = wechatH5UserPO.getAccountInfoId();
                boolean binded = this.bindedMobile(userId);
                log.info(":>>> 用户:{},是否绑定手机号:{}", userId, binded);
                UserPO userPO = new UserPO();
                BeanUtils.copyProperties(wechatH5UserPO, userPO);
                userPO.setId(userId);
                userPO.setCheckedMobile(binded);
                return userPO;
            }
            case "wechat-mini": {
                log.info(":>>> 平台:wechat-mini");
                Query query = new Query().addCriteria(Criteria.where("openId").is(openId));
                if (StringUtils.isNotBlank(appId)) {
                    query.addCriteria(Criteria.where("appId").is(appId));
                }
                String userId = null;
                WechatMiniUserPO wechatMiniUserPO = mongoTemplate.findOne(query, WechatMiniUserPO.class);
                if (Objects.isNull(wechatMiniUserPO)) {
                    log.error(":>>> 微信小程序用户不存在:{}", openId);
                    return null;
                }
                userId = wechatMiniUserPO.getAccountInfoId();
                UserPO userPO = new UserPO();
                BeanUtils.copyProperties(wechatMiniUserPO, userPO);
                userPO.setId(userId);
                return userPO;
            }
            case "douyin-mini": {
                log.info(":>>> 平台:douyin-mini");
                Query query = new Query().addCriteria(Criteria.where("openId").is(openId));
                if (StringUtils.isNotBlank(appId)) {
                    query.addCriteria(Criteria.where("appId").is(appId));
                }
                String userId = null;
                DouYinMiniUserPO douYinMiniUserPO = mongoTemplate.findOne(query, DouYinMiniUserPO.class);
                if (Objects.isNull(douYinMiniUserPO)) {
                    log.error(":>>> 抖音小程序用户不存在:{}", openId);
                    return null;
                }
                userId = douYinMiniUserPO.getAccountInfoId();
                UserPO userPO = new UserPO();
                BeanUtils.copyProperties(douYinMiniUserPO, userPO);
                userPO.setId(userId);
                return userPO;
            }
            default:
                break;
        }
        return null;
    }

    @Override
    public UserPO getUserUserId(String platform, String appId, String userId) {
        log.info(":>>> 开始获取用户信息 platform:{},appId:{},userId:{}", platform, appId, userId);
        if (StringUtils.isBlank(platform) || StringUtils.isBlank(userId)) {
            log.error(":>>> 获取用户信息参数错误:平台或userId为空");
            throw new BusinessException("获取用户信息参数错误");
        }
        switch (platform) {
            case "qq-h5":
                log.info(":>>> 平台:qq-h5");
                Query queryQ = new Query().addCriteria(Criteria.where("accountInfoId").is(userId));
                QQH5UserPO qQH5UserPO = mongoTemplate.findOne(queryQ, QQH5UserPO.class);
                if (Objects.isNull(qQH5UserPO)) {
                    log.error(":>>> QQ用户不存在:{}", userId);
                    return null;
                }
                UserPO userPOQQ = new UserPO();
                BeanUtils.copyProperties(qQH5UserPO, userPOQQ);
                userPOQQ.setId(userId);
                return userPOQQ;
            case "qq":
                log.info(":>>> 平台:qq");
                return this.getUser(userId);
            case "wechat-h5":
                log.info(":>>> 平台:wechat-h5");
                Query query = new Query().addCriteria(Criteria.where("accountInfoId").is(userId));
//                if (StringUtils.isNotBlank(appId)) {
//                    query.addCriteria(Criteria.where("appId").is(appId));
//                }
                WechatH5UserPO wechatH5UserPO = mongoTemplate.findOne(query, WechatH5UserPO.class);
                if (Objects.isNull(wechatH5UserPO)) {
                    log.error(":>>> 微信用户不存在:{}", userId);
                    return null;
                }
                UserPO userPO = new UserPO();
                BeanUtils.copyProperties(wechatH5UserPO, userPO);
                userPO.setId(userId);
                return userPO;
            case "wechat-mini":
                query = new Query().addCriteria(Criteria.where("accountInfoId").is(userId));
                WechatMiniUserPO wechatMiniUserPO = mongoTemplate.findOne(query, WechatMiniUserPO.class);
                if (Objects.isNull(wechatMiniUserPO)) {
                    log.error(":>>> 微信用户不存在:{}", userId);
                    return null;
                }
                UserPO miniUser = new UserPO();
                BeanUtils.copyProperties(wechatMiniUserPO, miniUser);
                miniUser.setId(userId);
                return miniUser;
            case "douyin-mini": {
                log.info(":>>> 平台:douyin-mini");
                query = new Query().addCriteria(Criteria.where("accountInfoId").is(userId));
                DouYinMiniUserPO douYinMiniUserPO = mongoTemplate.findOne(query, DouYinMiniUserPO.class);
                if (Objects.isNull(douYinMiniUserPO)) {
                    log.error(":>>> 抖音小程序用户不存在:{}", userId);
                    return null;
                }
                userId = douYinMiniUserPO.getAccountInfoId();
                UserPO userDouYin = new UserPO();
                BeanUtils.copyProperties(douYinMiniUserPO, userDouYin);
                userDouYin.setId(userId);
                return userDouYin;
            }
            default:
                break;
        }
        return null;
    }


    @Override
    public UserPO getUserByPlatformAndUserId(String platform, String userId) {
        log.info("getUserByPlatformAndUserId platform:{},userId:{}", platform, userId);
        if (StringUtils.isAnyBlank(platform, userId)) {
            throw new BusinessException("获取用户信息参数错误");
        }
        if (PlatformEnum.QQ_H5.getValue().equals(platform)) {
            Query queryQ = new Query().addCriteria(Criteria.where("accountInfoId").is(userId));
            QQH5UserPO qQH5UserPO = mongoTemplate.findOne(queryQ, QQH5UserPO.class);
            if (Objects.isNull(qQH5UserPO)) {
                log.error("getUserByPlatformAndUserId 用户不存在 userId:{}, platform:{}", userId, platform);
                return null;
            }
            UserPO userPOQQ = new UserPO();
            BeanUtils.copyProperties(qQH5UserPO, userPOQQ);
            userPOQQ.setId(userId);
            return userPOQQ;
        }
        if (PlatformEnum.QQ.getValue().equals(platform)) {
            log.error("getUserByPlatformAndUserId 用户不存在 userId:{}, platform:{}", userId, platform);
            return this.getUser(userId);
        }
        if (PlatformEnum.WECHAT_H5.getValue().equals(platform)) {
            log.info(":>>> 平台:wechat-h5");
            Query query = new Query().addCriteria(Criteria.where("accountInfoId").is(userId));
            WechatH5UserPO wechatH5UserPO = mongoTemplate.findOne(query, WechatH5UserPO.class);
            if (Objects.isNull(wechatH5UserPO)) {
                log.error(":>>> 微信用户不存在:{}", userId);
                return null;
            }
            UserPO userPO = new UserPO();
            BeanUtils.copyProperties(wechatH5UserPO, userPO);
            userPO.setId(userId);
            return userPO;
        }

        if (PlatformEnum.WECHAT_MINI.getValue().equals(platform)) {
            Query query = new Query().addCriteria(Criteria.where("accountInfoId").is(userId));
            WechatMiniUserPO wechatMiniUserPO = mongoTemplate.findOne(query, WechatMiniUserPO.class);
            if (Objects.isNull(wechatMiniUserPO)) {
                log.error(":>>> 微信用户不存在:{}", userId);
                return null;
            }
            UserPO miniUser = new UserPO();
            BeanUtils.copyProperties(wechatMiniUserPO, miniUser);
            miniUser.setId(userId);
            return miniUser;
        }
        if (PlatformEnum.DOUYIN_MINI.getValue().equals(platform)) {
            log.info(":>>> 平台:douyin-mini");
            Query query = new Query().addCriteria(Criteria.where("accountInfoId").is(userId));
            DouYinMiniUserPO douYinMiniUserPO = mongoTemplate.findOne(query, DouYinMiniUserPO.class);
            if (Objects.isNull(douYinMiniUserPO)) {
                log.error(":>>> 抖音小程序用户不存在:{}", userId);
                return null;
            }
            userId = douYinMiniUserPO.getAccountInfoId();
            UserPO userDouYin = new UserPO();
            BeanUtils.copyProperties(douYinMiniUserPO, userDouYin);
            userDouYin.setId(userId);
            return userDouYin;
        }
        return null;
    }


    @Override
    public UserPO getUserByOpenId(String openId) {
        log.info(":>>> 开始获取用户信息openId:{}", openId);
        if (StringUtils.isBlank(openId)) {
            log.info(":>>> 获取用户信息openId:为空");
            throw new BusinessException("openId为空");
        }
        Query query1 = new Query().addCriteria(Criteria.where("openId").is(openId));
        UserPO userPO = mongoTemplate.findOne(query1, UserPO.class);
        if (Objects.nonNull(userPO) && StringUtils.isBlank(userPO.getAvatarUrl())) {
            userPO.setAvatarUrl(defaultHeadUrl);
        }
        return userPO;
    }

    /**
     * 获取用户
     *
     * @param userId
     * @return
     */
    @Override
    public UserPO getUser(String userId) throws BusinessException {
        Query query = new Query().addCriteria(Criteria.where("id").is(userId));
        UserPO userPO = mongoTemplate.findOne(query, UserPO.class);
        if (Objects.isNull(userPO)) {
            log.error(":>>> 用户:{} 不存在", userId);
            throw new BusinessException("用户不存在");
        }
        if (Objects.nonNull(userPO) && StringUtils.isBlank(userPO.getAvatarUrl())) {
            userPO.setAvatarUrl(defaultHeadUrl);
        }
        return userPO;
    }

    @Override
    public VisitorUserInfoRes getVisitorUerInfo(String userId, UserPO po) {
        log.info(":>>> 获取C端用户信息:{}", userId);
        if (StringUtils.isBlank(userId)) {
            log.error(":>>> 用户ID 为空", userId);
            throw new BusinessException("用户ID为空");
        }
        UserPO userPO = po;
        if (Objects.nonNull(userPO) && StringUtils.isBlank(userPO.getAvatarUrl())) {
            userPO.setAvatarUrl(defaultHeadUrl);
        }
        VisitorUserInfoRes res = new VisitorUserInfoRes();
        res.setAvatarUrl(userPO.getAvatarUrl());
        res.setNickName(userPO.getNickName());
        res.setGender(userPO.getGender());
        res.setName(userPO.getName());
        res.setBinded(po.getBinded());
        res.setCheckedMobile(po.getCheckedMobile());
        Integer partTimeJobDuration = jobInfoService.getPartTimeJobDuration(userId);
        res.setPartTimeJobDutaion(partTimeJobDuration);
//        Integer activityDuration = activityService.getVolunteerDuration(userId);
//        res.setVolunteerDutaion(activityDuration);
        log.info(":>>> 用户:{} 基本信息:{}", userId, JSON.toJSONString(res));
        Query queryM = new Query();
        MemberShipInfo memberShipInfo = mongoTemplate.findOne(queryM, MemberShipInfo.class);
        if (Objects.isNull(memberShipInfo)) {
            res.setMemberShiped(false);
            //     * 状态,0:待发布,1:已发布,2:已停用
            Query query = new Query().addCriteria(Criteria.where("status").is(1));
            memberShipInfo = mongoTemplate.findOne(query, MemberShipInfo.class);
            res.setMemberShipInfo(memberShipInfo);
            res.setOpenId(userPO.getOpenId());
            log.info(":>>> 用户:{},会员卡信息:{}", userId, JSON.toJSONString(memberShipInfo));
            return res;
        }
        res.setMemberShiped(true);
        res.setMemberShipInfo(memberShipInfo);
        res.setOpenId(userPO.getOpenId());
        res.setUniversityId(userPO.getUniversityId());
        if (StringUtils.isNotBlank(userPO.getUniversityId())) {
            Query queryU = new Query();
            queryU.addCriteria(Criteria.where("id").is(userPO.getUniversityId()));
            UniversityInfo universityInfo = mongoTemplate.findOne(queryM, UniversityInfo.class);
            if (Objects.nonNull(universityInfo)) {
                res.setUniversityName(universityInfo.getName());
            }
        }
        res.setEmail(userPO.getEmail());
        res.setQqNumber(userPO.getQqNumber());
        res.setProvince(userPO.getProvince());
        res.setMobile(userPO.getMobile());
        log.info(":>>> 用户:{},会员卡信息:{}", userId, JSON.toJSONString(memberShipInfo));
        return res;
    }

    @Override
    public void save(UserPO userPO) {
        log.info(":>>> 开始保存用户信息:{}", JSON.toJSONString(userPO));
        userPO.setUpdatedTime(new Date());
        if (StringUtils.isNotBlank(userPO.getUniversityId())) {
            Query query = new Query().addCriteria(Criteria.where("id").is(userPO.getUniversityId()));
            UniversityBase universityBase = mongoTemplate.findOne(query, UniversityBase.class);
            if (Objects.nonNull(universityBase)) {
                userPO.setUniversityName(universityBase.getName());
            }
        }
        mongoTemplate.save(userPO);

    }

    @Override
    @Async
    public void updateMovementStep(String userId, Date date, Integer step) {
        log.info(":>>> 开始更新运动步数用户:{},{},{}", userId, date, step);
        if (Objects.isNull(date) || Objects.isNull(step) || StringUtils.isBlank(userId)) {
            log.info(":>>> 更新运动步数用户:{},{},{} 参数错误", userId, date, step);
            return;
        }
        String userKey = String.format(userMoveFormatKey, userId);
        String dateStr = TimeUtils.parse(date, "yyyy-MM-dd");
        try {
            if (!this.isAttendance(userId, "60485c3a26740afef3e96519", date)) {
                redisTemplate.opsForHash().put(userKey, dateStr, step);
                log.info(":>>> 更新用户:{},天:{},运动步数:{}", userId, dateStr, step);
                return;
            } else {
                log.info(":>>> 用户:{},{} 已经打卡", userId, date);
            }
        } catch (Exception e) {
            log.error(":>>> 更新用户:{},{},步数:{} 错误:{}", userId, dateStr, step, e.getMessage());
        }

        return;
    }

    @Override
    public Integer getMovemeStep(String userId, Date date) {
        log.info(":>>> 开始获取运动步数用户:{},{}", userId, date);
        Integer step = 0;
        if (Objects.isNull(date) || StringUtils.isBlank(userId)) {
            log.info(":>>> 获取运动步数用户:{},{},{} 参数错误", userId, date);
            return 0;
        }
        String userKey = String.format(userMoveFormatKey, userId);
        String dateStr = TimeUtils.parse(date, "yyyy-MM-dd");
        try {
            Object o = redisTemplate.opsForHash().get(userKey, dateStr);
            if (Objects.isNull(o)) {
                Integer s = this.getRandom(1000, 50);
                log.info(":>>> 用户:{},日期:{} 步数不存在,设置步数:{}", userId, date, s);
                redisTemplate.opsForHash().put(userKey, dateStr, s);
            } else {
                step = (Integer) redisTemplate.opsForHash().get(userKey, dateStr);
            }


        } catch (Exception e) {
            log.error(":>>> 获取用户:{},{},步数:{} 错误:{}", userId, dateStr, e.getMessage());
        }
        log.info(":>>> 获取用户:{},{},步数:{}", userId, dateStr, step);
        return step;
    }

    /**
     * 更新用户信息
     *
     * @param userInfo
     */
    @Override
    public void updateUser(UserPO userInfo) {
        log.info(":>>> 开始更新用户信息:{}", JSON.toJSONString(userInfo));
        try {
            if (Objects.isNull(userInfo) || StringUtils.isBlank(userInfo.getId())) {
                log.error(":>>> 更新用户参数错误:ID或更新目的错误");
                return;
            }
            Query query = new Query();
            query.addCriteria(Criteria.where("id").is(userInfo.getId()));
            UserPO user = mongoTemplate.findOne(query, UserPO.class);
            if (Objects.isNull(user)) {
                log.error(":>>> 用户信息错误:用户:{} 不存在", userInfo.getId());
                return;
            }

            Update update = new Update();
            boolean isUpdate = false;
            if (!StringUtils.isEmpty(userInfo.getGender()) &&
                    (StringUtils.isBlank(user.getGender()) || !user.getGender().equals(userInfo.getGender()))) {
                update.set("gender", userInfo.getGender());
                isUpdate = true;
            }
            if (!org.springframework.util.StringUtils.isEmpty(userInfo.getAvatarUrl()) &&
                    (StringUtils.isBlank(user.getAvatarUrl()) || !user.getAvatarUrl().equals(userInfo.getAvatarUrl()))) {
                update.set("avatarUrl", userInfo.getAvatarUrl());
                isUpdate = true;
            }
            if (!org.springframework.util.StringUtils.isEmpty(userInfo.getNickName()) &&
                    (StringUtils.isBlank(user.getNickName()) || !user.getNickName().equals(userInfo.getNickName()))) {
                update.set("nickName", userInfo.getNickName());
                isUpdate = true;
            }
            if (!org.springframework.util.StringUtils.isEmpty(userInfo.getUniversityValue()) &&
                    (StringUtils.isBlank(user.getUniversityValue()) || !user.getUniversityValue().equals(userInfo.getUniversityValue()))) {
                update.set("universityValue", userInfo.getUniversityValue());
                update.set("universityName", userInfo.getUniversityName());
                isUpdate = true;
            }
            if (!org.springframework.util.StringUtils.isEmpty(userInfo.getMajor()) &&
                    (StringUtils.isBlank(user.getMajor()) || !user.getMajor().equals(userInfo.getMajor()))) {
                update.set("major", userInfo.getMajor());
                isUpdate = true;
            }
            if (!org.springframework.util.StringUtils.isEmpty(userInfo.getMobile()) &&
                    (StringUtils.isBlank(user.getMobile()) || !user.getMobile().equals(userInfo.getMobile()))) {
                update.set("mobile", userInfo.getMobile());
                update.set("gainMobileTime", new Date());
                isUpdate = true;
            }
            if (!org.springframework.util.StringUtils.isEmpty(userInfo.getQqNumber()) &&
                    (StringUtils.isBlank(user.getQqNumber()) || !user.getQqNumber().equals(userInfo.getQqNumber()))) {
                update.set("qqNumber", userInfo.getQqNumber());
                isUpdate = true;
            }
            if (!org.springframework.util.StringUtils.isEmpty(userInfo.getName()) &&
                    (StringUtils.isBlank(user.getName()) || !user.getName().equals(userInfo.getName()))) {
                update.set("name", userInfo.getName());
                isUpdate = true;
            }

            if (StringUtils.isNotBlank(userInfo.getSignature()) && !userInfo.getSignature().equals(user.getSignature())) {
                update.set("signature", userInfo.getSignature());
                isUpdate = true;
            }
            if (userInfo.getLabels() != null && userInfo.getLabels().size() > 0) {
                update.set("labels", userInfo.getLabels());
            }
            if (StringUtils.isNotBlank(userInfo.getUniversityId())) {
                update.set("universityId", userInfo.getUniversityId());
                isUpdate = true;
            }
            if (StringUtils.isNotBlank(userInfo.getProvince())) {
                update.set("province", userInfo.getProvince());
                isUpdate = true;
            }
            if (StringUtils.isNotBlank(userInfo.getCity())) {
                update.set("city", userInfo.getCity());
                isUpdate = true;
            }
            if (StringUtils.isNotBlank(userInfo.getFullAddress())) {
                update.set("fullAddress", userInfo.getFullAddress());
                isUpdate = true;
            }
            if (Objects.nonNull(userInfo.getBinded())) {
                update.set("binded", userInfo.getBinded());
                isUpdate = true;
            }
            if (StringUtils.isNotBlank(userInfo.getUniversityId())) {
                Query queryU = new Query().addCriteria(Criteria.where("id").is(userInfo.getUniversityId()));
                UniversityBase universityBase = mongoTemplate.findOne(queryU, UniversityBase.class);
                if (Objects.nonNull(universityBase)) {
                    update.set("universityName", universityBase.getName());
                    update.set("universityLogo", universityBase.getLogo());
                    if (StringUtils.isBlank(user.getProvince())) {
                        update.set("province", universityBase.getProvince());
                    }
                    if (StringUtils.isBlank(user.getCity())) {
                        update.set("city", universityBase.getCity());
                    }
                    isUpdate = true;
                }
            }
            if (isUpdate) {
                this.mongoTemplate.updateFirst(query, update, UserPO.class);
            }
        } catch (Exception e) {
            log.error(":>>> 更新用户信息错误:{}", e.getMessage());
        }

    }

    @Override
    public HashMap<String, UserPO> getByUserIds(List<String> ids) {
        Date start = new Date();
        log.info(":>>> 开始查询用户信息:{}", JSON.toJSONString(ids));
        HashMap<String, UserPO> res = new HashMap<>();
        if (CollectionUtils.isEmpty(ids)) {
            return res;
        }
        Query query1 = new Query().addCriteria(Criteria.where("id").in(ids));
        List<UserPO> userPOS = mongoTemplate.find(query1, UserPO.class);
        if (Objects.isNull(userPOS) || CollectionUtils.isEmpty(userPOS))
            return res;
        for (UserPO userPO : userPOS) {
            res.put(userPO.getId(), userPO);
        }
        log.info(":>>>  结束查询用户信息耗时:{} 毫秒", System.currentTimeMillis() - start.getTime());
        return res;
    }

    @Override
    public UserPO findUser(String mobile, String platform, String appId) {
        log.info(":>>> 开始查找用户:{},应用:{},平台:{}", mobile, appId, platform);
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(platform)) {
            log.error(":>>> 查询用户信息错误:参数错误");
            throw new BusinessException("查询用户信息错误:参数错误");
        }
        switch (platform) {
            case "qq":
                log.info(":>>> 平台来自:QQ");
                return null;
            case "wechat-h5": {
                log.info(":>>> 平台来自:wechat-h5");
                Query query = new Query().addCriteria(Criteria.where("mobile").is(mobile));
                if (Objects.nonNull(appId)) {
                    query.addCriteria(Criteria.where("appId").is(appId));
                } else {
                    query.addCriteria(Criteria.where("appId").is("wxfad57b68ee0d212d"));
                }
                WechatH5UserPO userPO = mongoTemplate.findOne(query, WechatH5UserPO.class);
                if (Objects.nonNull(userPO)) {
                    UserPO userPO1 = new UserPO();
                    BeanUtils.copyProperties(userPO, userPO1);
                    userPO1.setId(userPO.getAccountInfoId());
                    if (Objects.nonNull(userPO1) && StringUtils.isBlank(userPO1.getAvatarUrl())) {
                        userPO.setAvatarUrl(defaultHeadUrl);
                    }
                    log.info(":>>> 查询的用户信息:{}", JSON.toJSONString(userPO1));
                    return userPO1;
                }
                return null;
            }

            default:
                break;
        }
        return null;
    }

    @Override
    public String getUserProvince(String acitivityId, String userId) {
        log.info(":>>> 开始获取用户所在省userId:{},acitivityId:{}", userId, acitivityId);
        if (StringUtils.isBlank(userId)) {
            log.error(":>>> 获取用户所在省错误:userId为空");
            return "";
        }
        Query query = new Query().addCriteria(Criteria.where("userId").is(userId).and("activityId").is(acitivityId).and("joined").is(Boolean.TRUE));
        UserParticipateActivityInfo up = mongoTemplate.findOne(query, UserParticipateActivityInfo.class);
        if (Objects.nonNull(up) && StringUtils.isNotBlank(up.getUniversityId())) {
            log.info(":>>> 获取用户参与活动记录失败 userId:{},acitivityId:{}", userId, acitivityId);
            UniversityInfo universityInfo = universityInfoService.getCache(up.getUniversityId());
            if (Objects.nonNull(universityInfo)) {
                log.info(":>>> 大学信息存在:{}", up.getUniversityId());
                return universityInfo.getProvince();
            }

        } else {
            log.info(":>>> 获取用户参与活动记录失败 userId:{},acitivityId:{}", userId, acitivityId);
            Query queryU = new Query().addCriteria(Criteria.where("accountInfoId").is(userId));
            WechatH5UserPO wechatH5UserPO = mongoTemplate.findOne(queryU, WechatH5UserPO.class);
            if (Objects.isNull(wechatH5UserPO)) {
                log.info(":>>> 微信账户用户:{} 不存在", userId);
                return "";
            }
            if (Objects.nonNull(wechatH5UserPO)) {
                return wechatH5UserPO.getProvince();
            }
        }
        return "";
    }

    @Override
    public boolean checkedMobile(String userId) {
        log.info(":>>> 开始查询账户ID:{} 是否验证手机号", userId);
        Query query = new Query().addCriteria(Criteria.where("id").is(userId).and("checkedMobile").is(Boolean.TRUE));
        boolean exist = mongoTemplate.exists(query, UserPO.class);
        log.info(":>>> 账户:{} 是否验证手机号:{}", userId, exist);
        return exist;
    }

    @Async
    @Override
    public void updateAccountMobile(String id, String mobile) {
        log.info(":>>> 开始更新账户手机号:{}--{}", id, mobile);
        if (StringUtils.isBlank(id) || StringUtils.isBlank(mobile)) {
            log.error(":>>> 更新账户手机号错误:账户ID或手机号为空");
            return;
        }
        Date date = new Date();
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        Update update = new Update();
        update.set("mobile", mobile);
        update.set("checkedMobile", Boolean.TRUE);
        update.set("updatedTime", date);
        update.set("checkedMobileTime", date);
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, UserPO.class);
        log.info(":>>> 更新账户:{},手机号为:{},结果为:{}", id, mobile, updateResult.getModifiedCount() > 0 ? true : false);

    }


    @Override
    public UserPO find(String mobile, Boolean checkMobile) {
        log.info(":>>> 查询用户:{},{}", mobile, checkMobile);
        Query query = new Query().addCriteria(Criteria.where("mobile").is(mobile).and("checkMobile").is(Boolean.TRUE));
//        query.with(new Sort(new Sort.Order(Sort.Direction.ASC, "checkedMobileTime")));
        Sort sort = Sort.by(Sort.Direction.ASC, "checkedMobileTime");
        query.with(sort);
        UserPO userPO = mongoTemplate.findOne(query, UserPO.class);
        return userPO;
    }

    @Override
    public List<String> findCorrentMobileUserId(String mobile) {
        log.info(":>>> 查询mobile:相关联的手机号 {}", mobile);
        if (StringUtils.isBlank(mobile)) {
            throw new BusinessException("查询相关联的手机号为空");
        }
        List<String> userIds = new ArrayList<>();
        Query query = new Query().addCriteria(Criteria.where("mobile").is(mobile));
        List<WechatH5UserPO> wechatH5UserPOS = mongoTemplate.find(query, WechatH5UserPO.class);
        if (CollectionUtils.isNotEmpty(wechatH5UserPOS)) {
            for (WechatH5UserPO wechatH5UserPO : wechatH5UserPOS) {
                if (StringUtils.isNotBlank(wechatH5UserPO.getAccountInfoId())) {
                    userIds.add(wechatH5UserPO.getAccountInfoId());
                }
            }
        }
        List<UserPO> userPOS = mongoTemplate.find(query, UserPO.class);
        if (CollectionUtils.isNotEmpty(userPOS)) {
            for (UserPO userPO : userPOS) {
                if (StringUtils.isNotBlank(userPO.getId())) {
                    if (userIds.contains(userPO.getId()))
                        userIds.add(userPO.getId());
                }
            }
        }
        log.info(":>>> 用户:{} 相关联的账户ID:{}", mobile, JSON.toJSON(userIds));
        return userIds;
    }

    @Override
    public List<String> findCorrentUserId(String userId) {
        log.info(":>>> 开始查询相关的用户ID:{}", userId);
        Long start = System.currentTimeMillis();
        List<String> uids = new ArrayList<>();
        Query query = new Query().addCriteria(Criteria.where("id").is(userId));
        UserPO userPO = mongoTemplate.findOne(query, UserPO.class);
        if (Objects.isNull(userPO)) {
            log.error(":>>> 用户:{} 不存在", userId);
            return uids;
        }
        if (StringUtils.isBlank(userPO.getMobile())) {
            log.error(":>>> 用户:{} 手机号为空", userId);
            uids.add(userId);
            return uids;
        }
        Query queryM = new Query().addCriteria(Criteria.where("mobile").is(userPO.getMobile()));
        List<UserPO> userPOS = mongoTemplate.find(queryM, UserPO.class);
        if (CollectionUtils.isEmpty(userPOS)) {
            uids.add(userId);
            return uids;
        }
        for (UserPO userPO1 : userPOS) {
            if (!uids.contains(userPO1.getId())) {
                uids.add(userPO1.getId());
            }
        }
        if (!uids.contains(userId)) {
            uids.add(userId);
        }
        log.info(":>>> 用户:{} 相关联的用户uids:{},耗时:{} 豪秒", userId, JSON.toJSON(uids), (System.currentTimeMillis() - start) / 1000);
        return uids;
    }

    @Override
    public List<String> findSameMobiles(String userId) {
        log.info(":>>> 查找用户相关联的手机号 with userId:{}", userId);
        List<String> mobiles = new ArrayList<>();
        Query query = new Query().addCriteria(Criteria.where("accountInfoId").is(userId));
        List<WechatH5UserPO> wechatH5UserPOS = mongoTemplate.find(query, WechatH5UserPO.class);
        if (Objects.nonNull(wechatH5UserPOS) && !org.springframework.util.CollectionUtils.isEmpty(wechatH5UserPOS)) {
            for (WechatH5UserPO wechatH5UserPO : wechatH5UserPOS) {
                if (StringUtils.isNotBlank(wechatH5UserPO.getMobile()) && !mobiles.contains(wechatH5UserPO.getMobile())) {
                    mobiles.add(wechatH5UserPO.getMobile());
                }
            }
        }
        List<QQH5UserPO> qqUsers = mongoTemplate.find(query, QQH5UserPO.class);
        if (Objects.nonNull(qqUsers) && !org.springframework.util.CollectionUtils.isEmpty(qqUsers)) {
            for (QQH5UserPO qQH5UserPO : qqUsers) {
                if (StringUtils.isNotBlank(qQH5UserPO.getMobile()) && !mobiles.contains(qQH5UserPO.getMobile())) {
                    mobiles.add(qQH5UserPO.getMobile());
                }
            }
        }
        UserPO userPO = this.getUser(userId);
        if (Objects.nonNull(userPO) && StringUtils.isNotBlank(userPO.getMobile()) && !mobiles.contains(userPO.getMobile())) {
            mobiles.add(userPO.getMobile());
        }
        log.info(":>>> 用户:{} 关联的手机号:{}", userId, JSON.toJSON(mobiles));
        return mobiles;
    }

    @Override
    public UserPO find(String mobile) {
        log.info(":>>> 查询用户:{}", mobile);
        Query query = new Query().addCriteria(Criteria.where("mobile").is(mobile));
        Sort sort = Sort.by(Sort.Direction.DESC, "checkedMobileTime");
        query.with(sort);
        query.limit(100);
        UserPO userPO = mongoTemplate.findOne(query, UserPO.class);
        return userPO;
    }

    @Override
    public UserPO findByMiniOpenId(String miniOpenId) {
        log.info("findBYMiniOpenId 查询用户:{}", miniOpenId);
        Query query = new Query().addCriteria(Criteria.where("miniOpenId").is(miniOpenId));
        UserPO userPO = mongoTemplate.findOne(query, UserPO.class);
        return userPO;
    }

    @Override
    public UserPO createUser(CheckMobileVO req) {
        log.info("createUser 创建用户基础信息 req:{}", JSON.toJSONString(req));
        Date date = new Date();
        UserPO userPO = new UserPO();
        userPO.setOpenId(req.getMobile());
        userPO.setMiniOpenId(req.getMiniOpenId());
        userPO.setCreatedTime(date);
        userPO.setCheckedMobile(true);
        userPO.setMobile(req.getMobile());
        userPO.setCheckedMobileTime(date);
        userPO = mongoTemplate.insert(userPO);
        return userPO;
    }

    @Override
    public List<String> findCorrentUsers(String activityId, String userId) {
        List<String> userIds = new ArrayList<>();
        List<String> mobiles = this.findSameMobiles(userId);
        if (CollectionUtils.isEmpty(mobiles)) {
            userIds.add(userId);
            return userIds;
        }
        Query query = new Query().addCriteria(Criteria.where("mobile").in(mobiles).and("activityId").is(activityId));
        List<UserParticipateActivityInfo> ups = mongoTemplate.find(query, UserParticipateActivityInfo.class);
        if (Objects.isNull(ups) && CollectionUtils.isEmpty(ups)) {
            userIds.add(userId);
            return userIds;
        }
        for (UserParticipateActivityInfo up : ups) {
            if (StringUtils.isNotBlank(up.getUserId()) && !userIds.contains(up.getUserId())) {
                userIds.add(up.getUserId());
            }
        }
        log.info(":>>> 用户:{},活动:{} 相关联的用户ID:{}", userId, activityId, JSON.toJSONString(userIds));
        if (!userIds.contains(userId)) {
            userIds.add(userId);
        }
        return userIds;
    }

    @Override
    public UserPO find(String userId, String platform) {
        log.info(":>>> 开始查找用户:{},platform:{}", userId, platform);
        if (StringUtils.isBlank(platform)) {
            platform = "wechat-h5";
        }
        if (Objects.isNull(userId)) {
            return null;
        }
        Query query = new Query().addCriteria(Criteria.where("accountInfoId").is(userId));
        switch (platform) {
            // QQ 小程序
            case "qq": {
                QQMiniUserPO qqMiniUserPO = mongoTemplate.findOne(query, QQMiniUserPO.class);
                if (Objects.isNull(qqMiniUserPO)) {
                    return null;
                }
                UserPO userPO = new UserPO();
                BeanUtils.copyProperties(qqMiniUserPO, userPO);
                userPO.setId(userId);
                return userPO;
            }
            case "wechat-h5": {
                List<WechatH5UserPO> wechatH5UserPOs = mongoTemplate.find(query, WechatH5UserPO.class);
                WechatH5UserPO wechatH5UserPO = null;
                if (CollectionUtils.isEmpty(wechatH5UserPOs)) {
                    return null;
                }
                wechatH5UserPOs = getSortWechatUserList(wechatH5UserPOs);
                wechatH5UserPO = getQiniuWechatUser(wechatH5UserPOs);
                if (wechatH5UserPO == null) {
                    wechatH5UserPO = wechatH5UserPOs.get(0);
                }
                if (StringUtils.isBlank(wechatH5UserPO.getRankAvatarUrl())) {
                    wechatH5UserPO.setRankAvatarUrl(wechatH5UserPO.getAvatarUrl());
                }
                UserPO userPO = new UserPO();
                BeanUtils.copyProperties(wechatH5UserPO, userPO);
                userPO.setId(userId);
                return userPO;
            }
            case "h5": {
                H5UserPO h5UserPO = mongoTemplate.findOne(query, H5UserPO.class);
                if (Objects.isNull(h5UserPO)) {
                    return null;
                }
                UserPO userPO = new UserPO();
                BeanUtils.copyProperties(h5UserPO, userPO);
                userPO.setId(userId);
                return userPO;
            }
            default:
                break;
        }
        return null;
    }

    public List<WechatH5UserPO> getSortWechatUserList(List<WechatH5UserPO> wechatList) {
        return wechatList.stream().sorted(Comparator.comparing(WechatH5UserPO::getCreatedTime, Comparator.reverseOrder()))
                .collect(Collectors.toList());
    }

    public WechatH5UserPO getQiniuWechatUser(List<WechatH5UserPO> wechatList) {
        return wechatList.stream().filter(item ->
                        StringUtils.isNotBlank(item.getAvatarUrl()) && !item.getAvatarUrl().startsWith("https://thirdwx.qlogo.cn"))
                .findFirst().orElse(null);
    }

    public UserPO getDefaultUser() {
        log.info(":>>> 开始获取默认用户");
        Object o = stringRedisTemplate.opsForValue().get(String.format(defaultUserRedisKey, "default"));
        if (Objects.isNull(o)) {
            UserPO userPO = this.findUser("default", "wechat-h5", "default");
            if (Objects.nonNull(userPO)) {
                stringRedisTemplate.opsForValue().set(defaultUserRedisKey, JSON.toJSONString(userPO), 7, TimeUnit.DAYS);
                return userPO;
            } else {
                return null;
            }
        }
        return JSON.parseObject((String) o, UserPO.class);
    }

    @Override
    public HashMap<String, UserPO> getByUserIdsAndPlatform(List<String> ids, String platform, String appId) {
        log.info(":>>> 开始获取平台:{}用户信息:{}", platform, JSON.toJSON(ids));
        HashMap<String, UserPO> res = new HashMap<>();
        platform = StringUtils.isBlank(platform) ? "wechat-h5" : platform;
        switch (platform) {
            case "qq": {
                Query query = new Query().addCriteria(Criteria.where("accountInfoId").in(ids));
                List<QQMiniUserPO> pos = mongoTemplate.find(query, QQMiniUserPO.class);
                if (CollectionUtils.isEmpty(pos)) {
                    return res;
                }
                for (QQMiniUserPO qqMiniUserPO : pos) {
                    UserPO userPO = new UserPO();
                    BeanUtils.copyProperties(qqMiniUserPO, userPO);
                    userPO.setId(qqMiniUserPO.getAccountInfoId());
                    res.put(qqMiniUserPO.getAccountInfoId(), userPO);
                }
                return res;
            }
            case "wechat-h5": {
                Query query = new Query().addCriteria(Criteria.where("accountInfoId").in(ids));
                if (StringUtils.isNotBlank(appId)) {
                    query.addCriteria(Criteria.where("appId").is(appId));
                }
                List<WechatH5UserPO> pos = mongoTemplate.find(query, WechatH5UserPO.class);
                if (CollectionUtils.isEmpty(pos)) {
                    return res;
                }
                for (WechatH5UserPO qqMiniUserPO : pos) {
                    UserPO userPO = new UserPO();
                    BeanUtils.copyProperties(qqMiniUserPO, userPO);
                    userPO.setId(qqMiniUserPO.getAccountInfoId());
                    res.put(qqMiniUserPO.getAccountInfoId(), userPO);
                }
                return res;
            }
            case "wechat-mini": {
                Query query = new Query().addCriteria(Criteria.where("accountInfoId").in(ids));
                List<WechatMiniUserPO> pos = mongoTemplate.find(query, WechatMiniUserPO.class);
                if (CollectionUtils.isEmpty(pos)) {
                    return res;
                }
                for (WechatMiniUserPO qqMiniUserPO : pos) {
                    UserPO userPO = new UserPO();
                    BeanUtils.copyProperties(qqMiniUserPO, userPO);
                    userPO.setId(qqMiniUserPO.getAccountInfoId());
                    res.put(qqMiniUserPO.getAccountInfoId(), userPO);
                }
                return res;
            }
            case "douyin-mini": {
                Query query = new Query().addCriteria(Criteria.where("accountInfoId").in(ids));
                List<DouYinMiniUserPO> pos = mongoTemplate.find(query, DouYinMiniUserPO.class);
                if (CollectionUtils.isEmpty(pos)) {
                    return res;
                }
                for (DouYinMiniUserPO douYinMiniUserPO : pos) {
                    UserPO userPO = new UserPO();
                    BeanUtils.copyProperties(douYinMiniUserPO, userPO);
                    userPO.setId(douYinMiniUserPO.getAccountInfoId());
                    res.put(douYinMiniUserPO.getAccountInfoId(), userPO);
                }
                return res;
            }
            default:
                break;
        }
        return res;
    }

    @Override
    public String getUserProvince(UserPO userPO, String activityId) {
        Query queryU = new Query().addCriteria(Criteria.where("userId").is(userPO.getId()).and(
                "activityId").is(activityId));
        UserParticipateActivityInfo up = mongoTemplate.findOne(queryU, UserParticipateActivityInfo.class);
        if (Objects.nonNull(up) && StringUtils.isNotBlank(up.getUniversityId())) {
            Query query1 = new Query().addCriteria(Criteria.where("id").is(up.getUniversityId()));
            UniversityInfo universityInfo = mongoTemplate.findOne(query1, UniversityInfo.class);
            if (Objects.nonNull(universityInfo) && StringUtils.isNotBlank(universityInfo.getProvince())) {
                log.info(":>>> 省查询条件:{}", universityInfo.getProvince());
                return universityInfo.getProvince();
            }
        } else {
            if (StringUtils.isNotBlank(userPO.getUniversityId())) {
                Query query1 = new Query().addCriteria(Criteria.where("id").is(userPO.getUniversityId()));
                UniversityInfo universityInfo = mongoTemplate.findOne(query1, UniversityInfo.class);
                if (Objects.nonNull(universityInfo) && StringUtils.isNotBlank(universityInfo.getProvince())) {
                    log.info(":>>> 省查询条件:{}", universityInfo.getProvince());
                    return universityInfo.getProvince();
                }
            } else {
                if (StringUtils.isNotBlank(userPO.getProvince())) {
                    log.info(":>>> 省查询条件:{}", userPO.getProvince());
                    return userPO.getProvince();
                }
            }
        }
        return "";
    }

    @Override
    public boolean updateUserPo(UserPO userPO, String platform, String appId) {
        if (!Objects.nonNull(userPO) || StringUtils.isBlank(userPO.getId())) {
            return false;
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(userPO.getId()));
        Update update = new Update();
        boolean toUpdate = false;
        if (StringUtils.isNotBlank(userPO.getRankNickName())) {
            update.set("rankNickName", userPO.getRankNickName());
            toUpdate = true;
        }
        if (StringUtils.isNotBlank(userPO.getRankAvatarUrl())) {
            update.set("rankAvatarUrl", userPO.getRankAvatarUrl());
            toUpdate = true;
        }
        if (toUpdate) {
            UserPO userPO1 = this.find(userPO.getId(), platform);

            update.set("updatedTime", new Date());
            Query queryU = new Query().addCriteria(Criteria.where("accountInfoId").is(userPO.getId()));
            if (StringUtils.isNotBlank(appId)) {
                queryU.addCriteria(Criteria.where("appId").is(appId));
            }
            UpdateResult resultWechatH5 = mongoTemplate.updateMulti(queryU, update, WechatH5UserPO.class);
            UpdateResult resultQQMini = mongoTemplate.updateFirst(queryU, update, QQMiniUserPO.class);
            UpdateResult resultWechatMini = mongoTemplate.updateFirst(queryU, update, WechatMiniUserPO.class);
            UpdateResult result = mongoTemplate.updateFirst(query, update, UserPO.class);
            log.info(":>>> 修改账户:{},排行榜头像结果:微信H5:{},QQ小程序:{},微信小程序:{},账户:{}", userPO.getId(),
                    resultWechatH5.getModifiedCount(), resultQQMini.getModifiedCount(), resultWechatMini.getModifiedCount(),
                    result.getModifiedCount());
            //
            platform = StringUtils.isBlank(platform) ? "wechat-h5" : platform;
            String key = String.format(ALL_RANK_USER_KEY, userPO.getId(), platform);
            if (StringUtils.isNotBlank(userPO.getRankNickName())) {
                userPO1.setRankNickName(userPO.getRankNickName());
            }
            if (StringUtils.isNotBlank(userPO.getRankAvatarUrl())) {
                userPO1.setRankAvatarUrl(userPO.getRankAvatarUrl());
            }
            stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(userPO1), 1, TimeUnit.HOURS);
            return result.getModifiedCount() > 0 ? true : false;
        }
        return false;
    }

    @Override
    public String userUniversityId(String userId, String activityId) {
        Query queryU = new Query().addCriteria(Criteria.where("userId").is(userId).and(
                "activityId").is(activityId));
        UserParticipateActivityInfo up = mongoTemplate.findOne(queryU, UserParticipateActivityInfo.class);
        if (Objects.nonNull(up) && StringUtils.isNotBlank(up.getUniversityId())) {
            return up.getUniversityId();
        }
        return "";
    }

    @Override
    public UserPO saveOrUpdate(UserPO updateUser) {
        Query query = new Query();
        query.addCriteria(Criteria.where("unionId").is(updateUser.getUnionId()));
        Update update = new Update();
        update.set("openId", updateUser.getOpenId());
        update.set("appId", updateUser.getAppId());
        Date now = new Date();
        update.setOnInsert("createdTime", now);
        update.set("updatedTime", now);
        FindAndModifyOptions findAndModifyOptions = new FindAndModifyOptions();
        findAndModifyOptions.returnNew(Boolean.TRUE);
        findAndModifyOptions.upsert(Boolean.TRUE);

        return this.mongoTemplate.findAndModify(query, update, findAndModifyOptions, UserPO.class);
    }

    @Override
    public UserPO findUserByUserId(String userId) {
        if (StringUtils.isBlank(userId)) {
            return null;
        }
        return this.mongoTemplate.findById(userId, UserPO.class);
    }

    private Integer getRandom(Integer max, Integer min) {
        Random rand = new Random();
        int randNumber = rand.nextInt(max - min + 1) + min;
        log.info(":>>> ");
        return randNumber;
    }

    public boolean isAttendance(String userId, String activityId, Date date) {
        log.info(":>>> 开始判断用户:{},活动:{},日期:{},是否打卡", userId, activityId, date);
        String userKey = String.format(userDaKaRedisKey, userId, activityId);
        String dateStr = TimeUtils.parse(date, "yyyy-MM-dd");
        try {
            return redisTemplate.opsForHash().hasKey(userKey, dateStr);
        } catch (Exception e) {
            log.error(":>>> 判断用户:{},{},{} 是否打卡错误:{}", userId, activityId, date, e.getMessage());
            return false;
        }
    }

    /**
     * 是否绑定手机号
     *
     * @param id
     * @return
     */
    private boolean bindedMobile(String id) {
        Query query = new Query().addCriteria(Criteria.where("id").is(id).and("checkedMobile").is(Boolean.TRUE));
        boolean exist = mongoTemplate.exists(query, UserPO.class);
        return exist;
    }
}
